package edu.uis.csc478.spring09.threeoxen.requestprocessing.impl;

import edu.uis.csc478.spring09.threeoxen.requestprocessing.PantryManagementRequestProcessor;
import edu.uis.csc478.spring09.threeoxen.requestprocessing.RequestProcessingException;
import edu.uis.csc478.spring09.threeoxen.requestprocessing.StoreManagementRequestProcessor;
import edu.uis.csc478.spring09.threeoxen.requestprocessing.RequestProcessorFactory;
import edu.uis.csc478.spring09.threeoxen.persistence.pantry.Pantry;
import edu.uis.csc478.spring09.threeoxen.persistence.pantry.PantryRepository;
import edu.uis.csc478.spring09.threeoxen.persistence.pantry.GroceryList;
import edu.uis.csc478.spring09.threeoxen.persistence.pantry.Recipe;
import edu.uis.csc478.spring09.threeoxen.persistence.pantry.GroceryListItem;
import edu.uis.csc478.spring09.threeoxen.persistence.pantry.RecipeIngredient;
import edu.uis.csc478.spring09.threeoxen.persistence.PersistenceFactoryLoader;
import edu.uis.csc478.spring09.threeoxen.persistence.PersistenceManager;
import edu.uis.csc478.spring09.threeoxen.persistence.store.InventoryItem;
import edu.uis.csc478.spring09.threeoxen.persistence.store.Store;
import edu.uis.csc478.spring09.threeoxen.persistence.store.StoreRepository;
import edu.uis.csc478.spring09.threeoxen.persistence.store.GroceryItem;

import javax.swing.*;
import java.util.Date;
import java.util.ArrayList;

/**
 * User: Chris Logan
 * Date: Apr 29, 2009
 * Time: 12:49:21 PM
 */
public class PantryManagementRequestProcessorImpl implements PantryManagementRequestProcessor {

    @Override
    public void addPantry(String owningUser, int cubicCapacity) throws RequestProcessingException {
        Pantry pantry = PersistenceFactoryLoader.getInstance().getPantryObjectFactory().createPantry();
        pantry.setPantryOwnerName(owningUser);
        pantry.setCubicCapacity(cubicCapacity);

        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " already exists");
        }
        try {
            repository.addPantry(pantry);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to add pantry for " + owningUser, e);
        }
    }

    @Override
    public void addItemToPantry(String owningUser, String upcCode, int quantity) throws RequestProcessingException {
        InventoryItem item = PersistenceFactoryLoader.getInstance().getStoreObjectFactory().createInventoryItem();
        item.setUpcCode(upcCode);
        item.setInventoryCount(quantity);
        item.setInventoryAddedDate(new Date());

        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }

        StoreRepository repository2;
        try {
            repository2 = (StoreRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.STORE_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if(!repository2.groceryItemExists(upcCode)) {
            throw new RequestProcessingException("Item " + upcCode + " has not been defined");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        if (pantry.inPantry(upcCode)) {
            throw new RequestProcessingException("Item " + upcCode + " already in inventory");
        }
        try {
            pantry.addToPantry(item);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to add item " + upcCode + " to pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public void updateItemInPantry(String owningUser, String upcCode, int quantity) throws RequestProcessingException {
        InventoryItem item = PersistenceFactoryLoader.getInstance().getStoreObjectFactory().createInventoryItem();
        item.setUpcCode(upcCode);
        item.setInventoryCount(quantity);
        item.setInventoryAddedDate(new Date());

        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        if (!pantry.inPantry(upcCode)) {
            throw new RequestProcessingException("Item " + upcCode + " not in pantry");
        }
        try {
            pantry.updateInventoryInPantry(item);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to update item " + upcCode + " to pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public void removeItemInPantry(String owningUser, String upcCode) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        if (!pantry.inPantry(upcCode)) {
            throw new RequestProcessingException("Item " + upcCode + " not in pantry");
        }
        try {
            pantry.removeFromPantry(upcCode);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to delete item " + upcCode + " from pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public InventoryItem getItemInPantry(String owningUser, String upcCode) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        if (!pantry.inPantry(upcCode)) {
            throw new RequestProcessingException("Item " + upcCode + " not in pantry");
        }
        try {
            return pantry.getFromPantry(upcCode);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to get item " + upcCode + " from pantry belonging to " + owningUser, e);
        }
    }

    //grocery list methods

    @Override
    public void addGroceryListToPantry(String owningUser, String listName) throws RequestProcessingException {
        GroceryList list = PersistenceFactoryLoader.getInstance().getPantryObjectFactory().createGroceryList();
        list.setListName(listName);

        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        try {
            pantry.addGroceryList(list);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to add grocery list " + listName + " to pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public GroceryList getGroceryListInPantry(String owningUser, String listName) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        try {
            return pantry.getGroceryList(listName);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to get grocery list " + listName + " in pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public void deleteGroceryListFromPantry(String owningUser, String listName) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        try {
            pantry.deleteGroceryList(listName);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to delete grocery list " + listName + " in pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public void addItemToGroceryList(String owningUser, String listName, String upcCode, int quantity, double price, String recipeName, boolean manuallyOrdered) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        if(getGroceryItem(upcCode) == null) {
            throw new RequestProcessingException("Invalid UPC Code");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        try {
            GroceryList list = pantry.getGroceryList(listName);
            GroceryListItem item = PersistenceFactoryLoader.getInstance().getPantryObjectFactory().createGroceryListItem();
            item.setUpcCode(upcCode);
            item.setQuantity(quantity);
            item.setPrice(price);
            item.setRecipeName(recipeName);
            item.setManuallyOrdered(manuallyOrdered);
            list.addItemToList(item);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to add item to grocery list " + listName + " in pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public void updateItemQuantityInGroceryList(String owningUser, String listName, String upcCode, int quantity) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        if(getGroceryItem(upcCode) == null) {
            throw new RequestProcessingException("Invalid UPC Code");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        try {
            GroceryList list = pantry.getGroceryList(listName);
            list.updateItemQuantityInList(upcCode, quantity);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to update item in grocery list " + listName + " in pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public void removeItemFromGroceryList(String owningUser, String listName, String upcCode) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        if(getGroceryItem(upcCode) == null) {
            throw new RequestProcessingException("Invalid UPC Code");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        try {
            GroceryList list = pantry.getGroceryList(listName);
            list.removeItemFromList(upcCode);
            PersistenceManager.getInstance().updateRepository(repository);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to remove item from grocery list " + listName + " in pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public Object[] getItemsInGroceryList(String owningUser, String listName) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        try {
            return pantry.getGroceryList(listName).getGroceryListItems();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to get grocery list items " + listName + " in pantry belonging to " + owningUser, e);
        }
    }

    @Override
    public GroceryListItem getItemInGroceryList(String owningUser, String listName, String upcCode) throws RequestProcessingException {
        Pantry pantry = null;
        PantryRepository repository;
        try {
            repository = (PantryRepository) PersistenceManager.getInstance().getRepository(PersistenceManager.PANTRY_REPOSITORY);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Error loading repository", e);
        }
        if (!repository.pantryExists(owningUser)) {
            throw new RequestProcessingException("Pantry for " + owningUser + " does not exist");
        }
        pantry = repository.getPantryByOwnerName(owningUser);
        try {
            return pantry.getGroceryList(listName).getItemFromList(upcCode);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RequestProcessingException("Unable to get grocery list item " + upcCode +  " from " + listName + " in pantry belonging to " + owningUser, e);
        }
    }

    //recipe methods

    @Override
    public void addRecipeToPantry(String owningUser, String recipeName, int prepTime, int servings, int calories, String instructions) throws RequestProcessingException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void updateRecipeInPantry(String owningUser, String recipeName, int prepTime, int servings, int calories, String instructions) throws RequestProcessingException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Recipe getRecipeInPantry(String owningUser, String recipeName) throws RequestProcessingException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void deleteRecipeFromPantry(String owningUser, String recipeName) throws RequestProcessingException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void addIngredientToRecipe(String owningUser, String recipeName, String upcCode, String quantity) throws RequestProcessingException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void updateIngredientInRecipe(String owningUser, String recipeName, String upcCode, String quantity) throws RequestProcessingException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void removeIngredientFromRecipe(String owningUser, String recipeName, String upcCode) throws RequestProcessingException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public RecipeIngredient[] getIngredientsInRecipe(String owningUser, String recipeName, String upcCode) throws RequestProcessingException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    //utility method to make sure that upc codes that are used represent actual grocery items
    private GroceryItem getGroceryItem(String upcCode) {
        StoreManagementRequestProcessor processor = null;
        try {
            processor = (StoreManagementRequestProcessor) RequestProcessorFactory.getInstance().getRequestProcessor(RequestProcessorFactory.STORE_MGMT);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        try {
            return processor.getGroceryItem(upcCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
